package baiqi.sishen.community.service;

import baiqi.sishen.community.dto.CommentDTO;
import baiqi.sishen.community.enums.CommentTypeEnum;
import baiqi.sishen.community.enums.NotificationStatusEnum;
import baiqi.sishen.community.enums.NotificationTypeEnum;
import baiqi.sishen.community.execption.CustomizeErrorCode;
import baiqi.sishen.community.execption.CustomizeException;
import baiqi.sishen.community.mapper.*;
import baiqi.sishen.community.model.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 兕神
 * @version 1.0
 * DateTime: 2023/5/1
 */
@Service
public class CommentService {

    @Resource
    private CommentMapper commentMapper;

    @Resource
    private CommentExtMapper commentExtMapper;

    @Resource
    private QuestionExtMapper questionExtMapper;

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private NotificationMapper notificationMapper;

    /**
     * 实现评论的增加
     *
     * @param comment     comment
     * @param commentator 评论者(当前登录用户)
     */
    @Transactional//用于解决insert和incView的统一，实现原子性
    public void insert(Comment comment, User commentator) {
        //判断用户是否选中问题或评论
        if (comment.getParentId() == null || comment.getParentId() == 0) {
            //未选中问题
            throw new CustomizeException(CustomizeErrorCode.TARGET_PARAM_NOT_FOUND);
        }
        //判断该评论的类型是否合理
        if (comment.getType() == null || !CommentTypeEnum.isExist(comment.getType())) {
            //评论类型不合理
            throw new CustomizeException(CustomizeErrorCode.TYPE_PARAM_WRONG);
        }
        //添加时间
        comment.setGmtCreate(System.currentTimeMillis());
        comment.setGmtModified(comment.getGmtCreate());
        //判断评论的是评论还是问题
        if (comment.getType().equals(CommentTypeEnum.COMMENT.getType())) {
            //评论
            Comment dbComment = commentMapper.selectByPrimaryKey(comment.getParentId());
            if (dbComment == null) {
                throw new CustomizeException(CustomizeErrorCode.COMMENT_NOT_FOUND);
            }

            //评论的原问题
            QuestionExample questionExample = new QuestionExample();
            questionExample.createCriteria().andIdEqualTo(dbComment.getParentId());
            List<Question> questions = questionMapper.selectByExample(questionExample);
            if (questions.size() == 0) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }
            Question question = questions.get(0);

            //二级评论数加一
            Comment commentSimple = new Comment();
            commentSimple.setCommentCount(1L);
            commentSimple.setId(comment.getParentId());
            commentExtMapper.incCommentCount(commentSimple);

            //插入评论
            commentMapper.insert(comment);

            //给问题设置最后回复时间
            question.setGmtLatestComment(comment.getGmtCreate());
            questionMapper.updateByPrimaryKey(question);
            //创建通知
            createNotify(commentator.getName(), NotificationTypeEnum.REPLY_COMMENT, question.getTitle(),
                    question.getId(), dbComment.getCommentator(), commentator.getId(), dbComment.getContent());
        } else {
            //问题
            QuestionExample questionExample = new QuestionExample();
            questionExample.createCriteria()
                    .andIdEqualTo(comment.getParentId());
            List<Question> questions = questionMapper.selectByExampleWithBLOBs(questionExample);
            if (questions.size() == 0) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }
            //问题评论数加一
            Question question = questions.get(0);
            question.setCommentCount(1);
            question.setId(comment.getParentId());
            questionExtMapper.incCommentCount(question);

            //插入评论
            commentMapper.insert(comment);

            //给问题设置最后回复时间
            question.setGmtLatestComment(comment.getGmtCreate());
            questionMapper.updateByPrimaryKey(question);
            //创建通知
            question = questions.get(0);
            createNotify(commentator.getName(), NotificationTypeEnum.REPlY_QUESTION, question.getTitle(),
                    question.getId(), question.getCreator(), commentator.getId(), null);
        }

    }

    /**
     * 创建通知
     *
     * @param commentatorName      发通知者名字
     * @param notificationTypeEnum 通知类型是问题还是评论
     * @param questionTitle        问题题目
     * @param questionId           问题或评论的id
     * @param receiver             接受通知者id
     * @param notifier             发通知者id
     * @param commentTitle         问题的评论
     */
    private void createNotify(String commentatorName, NotificationTypeEnum notificationTypeEnum,
                              String questionTitle, Long questionId, Long receiver, Long notifier, String commentTitle) {
        Notification notification = new Notification();
        notification.setType(notificationTypeEnum.getType());
        notification.setGmtCreate(System.currentTimeMillis());

        notification.setNotifierName(commentatorName);
        notification.setQuestionTitle(questionTitle);
        notification.setQuestionId(questionId);
        notification.setCommentTitle(commentTitle);
        //设置未读
        notification.setStatus(NotificationStatusEnum.UNREAD.getStatus());
        notification.setReceiver(receiver);
        notification.setNotifier(notifier);
        //创建通知
        notificationMapper.insert(notification);
    }

    /**
     * 获取问题的评论
     *
     * @param id              问题id
     * @param commentTypeEnum CommentTypeEnum
     * @return CommentDTO
     */
    public List<CommentDTO> getCommentsByParentId(Long id, CommentTypeEnum commentTypeEnum) {
        //根据问题id获取评论
        CommentExample commentExample = new CommentExample();
        commentExample.createCriteria()
                .andParentIdEqualTo(id)
                .andTypeEqualTo(commentTypeEnum.getType());
        commentExample.setOrderByClause("gmt_create desc");//创建时间降序
        List<Comment> comments = commentMapper.selectByExample(commentExample);

        if (comments.size() == 0) {
            return new ArrayList<>();
        }

        //获取评论者的id并去重
        //Set<Long> collect = comments.stream().map(comment -> comment.getCommentator()).collect(Collectors.toSet());
        Set<Long> set = comments.stream().map(Comment::getCommentator).collect(Collectors.toSet());
        ArrayList<Long> ids = new ArrayList<>(set);

        //查询评论的用户并组成map
        UserExample userExample = new UserExample();
        userExample.createCriteria()
                .andIdIn(ids);
        List<User> users = userMapper.selectByExample(userExample);
        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));

        //填充user
        List<CommentDTO> commentDTOS = comments.stream().map(comment -> {
            CommentDTO commentDTO = new CommentDTO();
            BeanUtils.copyProperties(comment, commentDTO);
            commentDTO.setUser(userMap.get(comment.getCommentator()));
            return commentDTO;
        }).collect(Collectors.toList());
        return commentDTOS;
    }
}
